home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / cvs-1.8 / cvs-1 / cvs-1.8.1 / src / classify.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-06  |  11.6 KB  |  494 lines

  1. /*
  2.  * Copyright (c) 1992, Brian Berliner and Jeff Polk
  3.  * Copyright (c) 1989-1992, Brian Berliner
  4.  * 
  5.  * You may distribute under the terms of the GNU General Public License as
  6.  * specified in the README file that comes with the CVS 1.4 kit.
  7.  * 
  8.  */
  9.  
  10. #include "cvs.h"
  11.  
  12. #ifdef SERVER_SUPPORT
  13. static void sticky_ck PROTO((char *file, int aflag, Vers_TS * vers,
  14.                  List * entries,
  15.                  char *repository, char *update_dir));
  16. #else
  17. static void sticky_ck PROTO((char *file, int aflag, Vers_TS * vers, List * entries));
  18. #endif
  19.  
  20. /*
  21.  * Classify the state of a file
  22.  */
  23. Ctype
  24. Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
  25.            entries, rcsnode, versp, update_dir, pipeout)
  26.     char *file;
  27.     char *tag;
  28.     char *date;
  29.     char *options;
  30.     int force_tag_match;
  31.     int aflag;
  32.     char *repository;
  33.     List *entries;
  34.     RCSNode *rcsnode;
  35.     Vers_TS **versp;
  36.     char *update_dir;
  37.     int pipeout;
  38. {
  39.     Vers_TS *vers;
  40.     Ctype ret;
  41.     char *fullname;
  42.  
  43.     fullname = xmalloc (strlen (update_dir) + strlen (file) + 10);
  44.     if (update_dir[0] == '\0')
  45.     strcpy (fullname, file);
  46.     else
  47.     sprintf (fullname, "%s/%s", update_dir, file);
  48.  
  49.     /* get all kinds of good data about the file */
  50.     vers = Version_TS (repository, options, tag, date, file,
  51.                force_tag_match, 0, entries, rcsnode);
  52.  
  53.     if (vers->vn_user == NULL)
  54.     {
  55.     /* No entry available, ts_rcs is invalid */
  56.     if (vers->vn_rcs == NULL)
  57.     {
  58.         /* there is no RCS file either */
  59.         if (vers->ts_user == NULL)
  60.         {
  61.         /* there is no user file */
  62.         if (!force_tag_match || !(vers->tag || vers->date))
  63.             if (!really_quiet)
  64.             error (0, 0, "nothing known about %s", fullname);
  65.         ret = T_UNKNOWN;
  66.         }
  67.         else
  68.         {
  69.         /* there is a user file */
  70.         if (!force_tag_match || !(vers->tag || vers->date))
  71.             if (!really_quiet)
  72.             error (0, 0, "use `cvs add' to create an entry for %s",
  73.                    fullname);
  74.         ret = T_UNKNOWN;
  75.         }
  76.     }
  77.     else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
  78.     {
  79.         if (vers->ts_user == NULL)
  80.         /*
  81.          * Logically seems to me this should be T_UPTODATE.
  82.          * But the joining code in update.c seems to expect
  83.          * T_CHECKOUT, and that is what has traditionally been
  84.          * returned for this case.
  85.          */
  86.         ret = T_CHECKOUT;
  87.         else
  88.         {
  89.         error (0, 0, "use `cvs add' to create an entry for %s",
  90.                fullname);
  91.         ret = T_UNKNOWN;
  92.         }
  93.     }
  94.     else
  95.     {
  96.         /* there is an rcs file */
  97.  
  98.         if (vers->ts_user == NULL)
  99.         {
  100.         /* There is no user file; needs checkout */
  101.         ret = T_CHECKOUT;
  102.         }
  103.         else
  104.         {
  105.         if (pipeout)
  106.         {
  107.             /*
  108.              * The user file doesn't necessarily have anything
  109.              * to do with this.
  110.              */
  111.             ret = T_CHECKOUT;
  112.         }
  113.         /*
  114.          * There is a user file; print a warning and add it to the
  115.          * conflict list, only if it is indeed different from what we
  116.          * plan to extract
  117.          */
  118.         else if (No_Difference (file, vers, entries,
  119.                     repository, update_dir))
  120.         {
  121.             /* the files were different so it is a conflict */
  122.             if (!really_quiet)
  123.             error (0, 0, "move away %s; it is in the way",
  124.                    fullname);
  125.             ret = T_CONFLICT;
  126.         }
  127.         else
  128.             /* since there was no difference, still needs checkout */
  129.             ret = T_CHECKOUT;
  130.         }
  131.     }
  132.     }
  133.     else if (strcmp (vers->vn_user, "0") == 0)
  134.     {
  135.     /* An entry for a new-born file; ts_rcs is dummy */
  136.  
  137.     if (vers->ts_user == NULL)
  138.     {
  139.         /*
  140.          * There is no user file, but there should be one; remove the
  141.          * entry
  142.          */
  143.         if (!really_quiet)
  144.         error (0, 0, "warning: new-born %s has disappeared", fullname);
  145.         ret = T_REMOVE_ENTRY;
  146.     }
  147.     else
  148.     {
  149.         /* There is a user file */
  150.  
  151.         if (vers->vn_rcs == NULL)
  152.         /* There is no RCS file, added file */
  153.         ret = T_ADDED;
  154.         else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
  155.         /* we are resurrecting. */
  156.         ret = T_ADDED;
  157.         else
  158.         {
  159.         if (vers->srcfile->flags & INATTIC
  160.             && vers->srcfile->flags & VALID)
  161.         {
  162.             /* This file has been added on some branch other than
  163.                the one we are looking at.  In the branch we are
  164.                looking at, the file was already valid.  */
  165.             if (!really_quiet)
  166.             error (0, 0,
  167.                    "\
  168. conflict: %s has been added, but already exists",
  169.                    fullname);
  170.         }
  171.         else
  172.         {
  173.             /*
  174.              * There is an RCS file, so someone else must have checked
  175.              * one in behind our back; conflict
  176.              */
  177.             if (!really_quiet)
  178.             error (0, 0,
  179.                    "\
  180. conflict: %s created independently by second party",
  181.                    fullname);
  182.         }
  183.         ret = T_CONFLICT;
  184.         }
  185.     }
  186.     }
  187.     else if (vers->vn_user[0] == '-')
  188.     {
  189.     /* An entry for a removed file, ts_rcs is invalid */
  190.  
  191.     if (vers->ts_user == NULL)
  192.     {
  193.         char tmp[PATH_MAX];
  194.  
  195.         /* There is no user file (as it should be) */
  196.  
  197.         (void) sprintf (tmp, "-%s", vers->vn_rcs ? vers->vn_rcs : "");
  198.  
  199.         if (vers->vn_rcs == NULL)
  200.         {
  201.  
  202.         /*
  203.          * There is no RCS file; this is all-right, but it has been
  204.          * removed independently by a second party; remove the entry
  205.          */
  206.         ret = T_REMOVE_ENTRY;
  207.         }
  208.         else if (strcmp (tmp, vers->vn_user) == 0)
  209.  
  210.         /*
  211.          * The RCS file is the same version as the user file was, and
  212.          * that's OK; remove it
  213.          */
  214.         ret = T_REMOVED;
  215.         else
  216.         {
  217.  
  218.         /*
  219.          * The RCS file is a newer version than the removed user file
  220.          * and this is definitely not OK; make it a conflict.
  221.          */
  222.         if (!really_quiet)
  223.             error (0, 0,
  224.                "conflict: removed %s was modified by second party",
  225.                fullname);
  226.         ret = T_CONFLICT;
  227.         }
  228.     }
  229.     else
  230.     {
  231.         /* The user file shouldn't be there */
  232.         if (!really_quiet)
  233.         error (0, 0, "%s should be removed and is still there",
  234.                fullname);
  235.         ret = T_REMOVED;
  236.     }
  237.     }
  238.     else
  239.     {
  240.     /* A normal entry, TS_Rcs is valid */
  241.     if (vers->vn_rcs == NULL)
  242.     {
  243.         /* There is no RCS file */
  244.  
  245.         if (vers->ts_user == NULL)
  246.         {
  247.         /* There is no user file, so just remove the entry */
  248.         if (!really_quiet)
  249.             error (0, 0, "warning: %s is not (any longer) pertinent",
  250.                fullname);
  251.         ret = T_REMOVE_ENTRY;
  252.         }
  253.         else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
  254.         {
  255.  
  256.         /*
  257.          * The user file is still unmodified, so just remove it from
  258.          * the entry list
  259.          */
  260.         if (!really_quiet)
  261.             error (0, 0, "%s is no longer in the repository",
  262.                fullname);
  263.         ret = T_REMOVE_ENTRY;
  264.         }
  265.         else
  266.         {
  267.         /*
  268.          * The user file has been modified and since it is no longer
  269.          * in the repository, a conflict is raised
  270.          */
  271.         if (No_Difference (file, vers, entries,
  272.                    repository, update_dir))
  273.         {
  274.             /* they are different -> conflict */
  275.             if (!really_quiet)
  276.             error (0, 0,
  277.            "conflict: %s is modified but no longer in the repository",
  278.                fullname);
  279.             ret = T_CONFLICT;
  280.         }
  281.         else
  282.         {
  283.             /* they weren't really different */
  284.             if (!really_quiet)
  285.             error (0, 0,
  286.                    "warning: %s is not (any longer) pertinent",
  287.                    fullname);
  288.             ret = T_REMOVE_ENTRY;
  289.         }
  290.         }
  291.     }
  292.     else if (strcmp (vers->vn_rcs, vers->vn_user) == 0)
  293.     {
  294.         /* The RCS file is the same version as the user file */
  295.  
  296.         if (vers->ts_user == NULL)
  297.         {
  298.  
  299.         /*
  300.          * There is no user file, so note that it was lost and
  301.          * extract a new version
  302.          */
  303.         if (strcmp (command_name, "update") == 0)
  304.             if (!really_quiet)
  305.             error (0, 0, "warning: %s was lost", fullname);
  306.         ret = T_CHECKOUT;
  307.         }
  308.         else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
  309.         {
  310.  
  311.         /*
  312.          * The user file is still unmodified, so nothing special at
  313.          * all to do -- no lists updated, unless the sticky -k option
  314.          * has changed.  If the sticky tag has changed, we just need
  315.          * to re-register the entry
  316.          */
  317.         if (vers->entdata->options &&
  318.             strcmp (vers->entdata->options, vers->options) != 0)
  319.             ret = T_CHECKOUT;
  320.         else
  321.         {
  322. #ifdef SERVER_SUPPORT
  323.             sticky_ck (file, aflag, vers, entries,
  324.                    repository, update_dir);
  325. #else
  326.             sticky_ck (file, aflag, vers, entries);
  327. #endif
  328.             ret = T_UPTODATE;
  329.         }
  330.         }
  331.         else
  332.         {
  333.  
  334.         /*
  335.          * The user file appears to have been modified, but we call
  336.          * No_Difference to verify that it really has been modified
  337.          */
  338.         if (No_Difference (file, vers, entries,
  339.                    repository, update_dir))
  340.         {
  341.  
  342.             /*
  343.              * they really are different; modified if we aren't
  344.              * changing any sticky -k options, else needs merge
  345.              */
  346. #ifdef XXX_FIXME_WHEN_RCSMERGE_IS_FIXED
  347.             if (strcmp (vers->entdata->options ?
  348.                vers->entdata->options : "", vers->options) == 0)
  349.             ret = T_MODIFIED;
  350.             else
  351.             ret = T_NEEDS_MERGE;
  352. #else
  353.             ret = T_MODIFIED;
  354. #ifdef SERVER_SUPPORT
  355.             sticky_ck (file, aflag, vers, entries,
  356.                    repository, update_dir);
  357. #else
  358.             sticky_ck (file, aflag, vers, entries);
  359. #endif /* SERVER_SUPPORT */
  360. #endif
  361.         }
  362.         else
  363.         {
  364.             /* file has not changed; check out if -k changed */
  365.             if (strcmp (vers->entdata->options ?
  366.                vers->entdata->options : "", vers->options) != 0)
  367.             {
  368.             ret = T_CHECKOUT;
  369.             }
  370.             else
  371.             {
  372.  
  373.             /*
  374.              * else -> note that No_Difference will Register the
  375.              * file already for us, using the new tag/date. This
  376.              * is the desired behaviour
  377.              */
  378.             ret = T_UPTODATE;
  379.             }
  380.         }
  381.         }
  382.     }
  383.     else
  384.     {
  385.         /* The RCS file is a newer version than the user file */
  386.  
  387.         if (vers->ts_user == NULL)
  388.         {
  389.         /* There is no user file, so just get it */
  390.  
  391.         if (strcmp (command_name, "update") == 0)
  392.             if (!really_quiet)
  393.             error (0, 0, "warning: %s was lost", fullname);
  394.         ret = T_CHECKOUT;
  395.         }
  396.         else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
  397.         {
  398.  
  399.         /*
  400.          * The user file is still unmodified, so just get it as well
  401.          */
  402. #ifdef SERVER_SUPPORT
  403.             if (strcmp (vers->entdata->options ?
  404.                 vers->entdata->options : "", vers->options) != 0
  405.             || (vers->srcfile != NULL
  406.             && (vers->srcfile->flags & INATTIC) != 0))
  407.             ret = T_CHECKOUT;
  408.         else
  409.             ret = T_PATCH;
  410. #else
  411.         ret = T_CHECKOUT;
  412. #endif
  413.         }
  414.         else
  415.         {
  416.         if (No_Difference (file, vers, entries,
  417.                    repository, update_dir))
  418.             /* really modified, needs to merge */
  419.             ret = T_NEEDS_MERGE;
  420. #ifdef SERVER_SUPPORT
  421.             else if ((strcmp (vers->entdata->options ?
  422.                   vers->entdata->options : "", vers->options)
  423.               != 0)
  424.              || (vers->srcfile != NULL
  425.                  && (vers->srcfile->flags & INATTIC) != 0))
  426.             /* not really modified, check it out */
  427.             ret = T_CHECKOUT;
  428.         else
  429.             ret = T_PATCH;
  430. #else
  431.         else
  432.             /* not really modified, check it out */
  433.             ret = T_CHECKOUT;
  434. #endif
  435.         }
  436.     }
  437.     }
  438.  
  439.     /* free up the vers struct, or just return it */
  440.     if (versp != (Vers_TS **) NULL)
  441.     *versp = vers;
  442.     else
  443.     freevers_ts (&vers);
  444.  
  445.     free (fullname);
  446.  
  447.     /* return the status of the file */
  448.     return (ret);
  449. }
  450.  
  451. static void
  452. #ifdef SERVER_SUPPORT
  453. sticky_ck (file, aflag, vers, entries, repository, update_dir)
  454. #else
  455. sticky_ck (file, aflag, vers, entries)
  456. #endif
  457.     char *file;
  458.     int aflag;
  459.     Vers_TS *vers;
  460.     List *entries;
  461. #ifdef SERVER_SUPPORT
  462.     char *repository;
  463.     char *update_dir;
  464. #endif
  465. {
  466.     if (aflag || vers->tag || vers->date)
  467.     {
  468.     char *enttag = vers->entdata->tag;
  469.     char *entdate = vers->entdata->date;
  470.  
  471.     if ((enttag && vers->tag && strcmp (enttag, vers->tag)) ||
  472.         ((enttag && !vers->tag) || (!enttag && vers->tag)) ||
  473.         (entdate && vers->date && strcmp (entdate, vers->date)) ||
  474.         ((entdate && !vers->date) || (!entdate && vers->date)))
  475.     {
  476.         Register (entries, file, vers->vn_user, vers->ts_rcs,
  477.               vers->options, vers->tag, vers->date, vers->ts_conflict);
  478.  
  479. #ifdef SERVER_SUPPORT
  480.         if (server_active)
  481.         {
  482.         /* We need to update the entries line on the client side.
  483.            It is possible we will later update it again via
  484.            server_updated or some such, but that is OK.  */
  485.         server_update_entries
  486.           (file, update_dir, repository,
  487.            strcmp (vers->ts_rcs, vers->ts_user) == 0 ?
  488.            SERVER_UPDATED : SERVER_MERGED);
  489.         }
  490. #endif
  491.     }
  492.     }
  493. }
  494.